package com.imis.module.system.bus;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imis.base.annotation.VerificationCaptcha;
import com.imis.base.constant.CacheConstant;
import com.imis.base.constant.CommonConstant;
import com.imis.base.constant.enums.SysTipEnum;
import com.imis.base.globle.Result;
import com.imis.base.util.ConvertUtils;
import com.imis.base.util.CurrentUserUtils;
import com.imis.module.api.model.ro.SysRegisterRO;
import com.imis.module.base.BaseBus;
import com.imis.module.system.model.converter.SysUserConverter;
import com.imis.module.system.model.po.SysOrganization;
import com.imis.module.system.model.po.SysRole;
import com.imis.module.system.model.po.SysUser;
import com.imis.module.system.model.ro.*;
import com.imis.module.system.model.vo.SysUserVO;
import com.imis.module.system.service.ISysOrganizationService;
import com.imis.module.system.service.ISysRoleService;
import com.imis.module.system.service.ISysUserOrganizationService;
import com.imis.module.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * SysUserBus<br>
 * 用户相关功能业务处理类
 * </p>
 *
 * @author XinLau
 * @version 1.0
 * @since 2020年04月15日 11:54
 */
@Service
public class SysUserBus extends BaseBus {

    /**
     * 用户信息 服务类
     */
    private ISysUserService sysUserService;

    @Autowired
    public void setSysUserService(ISysUserService sysUserService) {
        this.sysUserService = sysUserService;
    }

    /**
     * 角色信息 服务类
     */
    private ISysRoleService sysRoleService;

    @Autowired
    public void setSysRoleService(ISysRoleService sysRoleService) {
        this.sysRoleService = sysRoleService;
    }

    /**
     * 组织机构 服务类
     */
    private ISysOrganizationService serviceBySysOrganizationService;

    @Autowired
    public void setISysOrganizationService(ISysOrganizationService serviceBySysOrganizationService) {
        this.serviceBySysOrganizationService = serviceBySysOrganizationService;
    }

    /**
     * 用户-组织机构关联表 服务类
     */
    private ISysUserOrganizationService sysUserOrganizationService;

    @Autowired
    public ISysUserOrganizationService getSysUserOrganizationService() {
        return sysUserOrganizationService;
    }

    /**
     * 添加用户校验
     *
     * @param sysUser - 系统用户
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/9 9:47
     */
    private Result userAddVerification(SysUser sysUser) {
        Result result = new Result<>();
        if (sysUser != null) {
//            情况1：根据用户信息查询，该用户已注销
            if (CommonConstant.DEL_FLAG_DELETE.equals(sysUser.getDelFlag())) {
                return result.errorFormat(SysTipEnum.USER_ADD_ERR_DELETE, sysUser.getUsername());
            }
//            情况2.根据用户信息查询，该用户已冻结
            if (CommonConstant.USER_FREEZE.equals(sysUser.getStatus())) {
                return result.errorFormat(SysTipEnum.USER_ADD_ERR_FREEZE, sysUser.getUsername());
            }
//            情况3.根据用户信息查询，该用户存在
            return result.errorFormat(SysTipEnum.USER_ADD_ERR_REPEAT, sysUser.getUsername());
        }
        return result;
    }

    /**
     * 为用户更新校验
     *
     * @param sysUserUpdateRo - 用户更新对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/20 14:18
     */
    private Result userUpdateVerification(SysUserUpdateRO sysUserUpdateRo) {
        if (sysUserUpdateRo != null) {
            if (ConvertUtils.isNotEmpty(sysUserUpdateRo.getId())) {
                SysUser sysUser = sysUserService.getById(sysUserUpdateRo.getId());
                if (sysUser != null) {
                    return Result.ok(sysUser);
                }
            }
        }
        return Result.errorsFormat(SysTipEnum.USER_UPDATE_ERR_NON);
    }

    /**
     * 为用户授权角色校验
     *
     * @param sysGrantUserToRole - 为用户授权角色校验
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/20 14:18
     */
    private Result grantRolesToUserVerification(SysGrantRolesToUserRO sysGrantUserToRole) {
//        1.验证用户合法性
        Long userId = sysGrantUserToRole.getUserId();
        SysUser sysUser = sysUserService.getById(userId);
        if (ConvertUtils.isEmpty(sysUser)) {
            return Result.errorsFormat(SysTipEnum.GRANT_ROLES_TO_USER_ERR_NON_USER, userId);
        }
//        2.验证角色合法性
        List<Long> roleIdList = sysGrantUserToRole.getRoleIdList();
        List<SysRole> sysRoleList = sysRoleService.listByIds(roleIdList);
        if (sysRoleList.size() != roleIdList.size()) {
            return Result.errorsFormat(SysTipEnum.GRANT_ROLES_TO_USER_ERR_NON_ROLE, roleIdList.toString());
        }
        return Result.ok();
    }

    /**
     * 分页查询用户信息
     *
     * @param pagingQueryUserDTO - 系统日志查询对象
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 15:47
     */
    public Result pagingQuerySysUserListByParameter(final PagingQueryUserDTO pagingQueryUserDTO) {
        try {
            Page<SysUserVO> sysLogSelectRoPage = sysUserService.pagingQuerySysUserListByParameter(pagingQueryUserDTO);
            return Result.ok(sysLogSelectRoPage);
        } catch (Exception e) {
            return Result.errorsFormat(SysTipEnum.USER_PAGE_QUERY_ERR, e.getMessage());
        }
    }

    /**
     * 添加用户
     *
     * @param sysRegister - 用户注册对象
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    public Result addUser(SysRegisterRO sysRegister) {
//        1、校验用户重复
        SysUser sysUser = sysUserService.queryUserByName(sysRegister.getUsername());
        Result result = userAddVerification(sysUser);
        if (!result.isSuccess()) {
            return result;
        }
//        2、创建新用户
        sysUser = SysUserConverter.INSTANCE.ro2Domain(sysRegister);
        sysUser.setCreateBy(Long.valueOf(CurrentUserUtils.getLoginUserId()));
        if (sysUserService.saveUser(sysUser)) {
            result.setResult(SysUserConverter.INSTANCE.domain2vo(sysUser));
            return result.success();
        }
        return result.errorFormat(SysTipEnum.USER_ADD_ERR, sysRegister.getUsername());
    }

    /**
     * 冻结用户
     *
     * @param identification - 用户唯一标识
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    public Result freezeUserByIdentification(final Long identification) {
        try {
//            1.判断用户是否存在
            SysUser sysUser = sysUserService.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getId, identification));
            if (ConvertUtils.isEmpty(sysUser)) {
                return Result.errorsFormat(SysTipEnum.USER_FREEZE_ERR_USER_NULL, identification);
            }
//            2.Redis缓存内取出要冻结账号缓存Token的Key
            String redisTokenKey = (String) redisUtil.hget(CacheConstant.PREFIX_SYS_USER_ID_TOKEN, sysUser.getId().toString());
            if (StrUtil.isNotEmpty(redisTokenKey)) {
                // 3.删除用户Token缓存，强制用户下线
                redisUtil.del(redisTokenKey);
                // 删除用户Token的Key缓存
                redisUtil.del(CacheConstant.PREFIX_SYS_USER_ID_TOKEN, sysUser.getId().toString());
            }
//            4.修改用户status - 状态(1：正常  2：冻结 ）
            Boolean freeze = sysUserService.freezeUserByIdentification(identification);
            if (!freeze) {
                return Result.errorsFormat(SysTipEnum.USER_FREEZE_ERR, identification);
            }
            return Result.ok();
        } catch (Exception e) {
            return Result.errorsFormat(SysTipEnum.USER_FREEZE_ERR, identification, e.getMessage());
        }
    }

    /**
     * 解冻用户
     *
     * @param identification - 用户唯一标识
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    public Result unFreezeUserByIdentification(final Long identification) {
        try {
//            修改用户status - 状态(1：正常  2：冻结 ）
            Boolean unFreeze = sysUserService.unFreezeUserByIdentification(identification);
            if (!unFreeze) {
                return Result.errorsFormat(SysTipEnum.USER_UNFREEZE_ERR, identification);
            }
            return Result.ok();
        } catch (Exception e) {
            return Result.errorsFormat(SysTipEnum.USER_UNFREEZE_ERR, identification, e.getMessage());
        }
    }

    /**
     * 查看用户
     *
     * @param identification - 用户唯一标识
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    public Result queryUserById(final Long identification) {
        SysUser sysUser = sysUserService.getById(identification);
        if (sysUser == null) {
            return Result.errorsFormat(SysTipEnum.USER_QUERY_ERR, identification);
        }
        return Result.ok(SysUserConverter.INSTANCE.domain2vo(sysUser));
    }

    /**
     * 更新用户信息
     *
     * @param sysUserUpdateRo - 用户信息
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    public Result updateById(SysUserUpdateRO sysUserUpdateRo) {
        // 1.验证信息合法
        Result result = userUpdateVerification(sysUserUpdateRo);
        if (!result.isSuccess()) {
            return result;
        }
        SysUser sysUser = (SysUser) result.getResult();
        SysUserConverter.INSTANCE.getUpdatePo(sysUserUpdateRo, sysUser);
//        2.更新用户信息
        boolean updateById = sysUserService.updateById(sysUser);
        if (updateById) {
//            TODO:This 更新用户信息缓存
            return Result.ok();
        }
        return Result.errorsFormat(SysTipEnum.USER_UPDATE_ERR, sysUserUpdateRo.getId());
    }

    /**
     * 用户授权角色
     *
     * @param sysGrantUserToRole - 用户授权角色
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/19 11:10
     */
    public Result grantRoleToUser(SysGrantRolesToUserRO sysGrantUserToRole) {
//        1.为用户授权角色校验
        Result result = grantRolesToUserVerification(sysGrantUserToRole);
        if (result.isSuccess()) {
//            2.授权操作
            boolean grant = sysUserService.grantRoleToUser(sysGrantUserToRole);
            if (grant) {
                return Result.ok();
            }
        }
        return Result.errorsFormat(SysTipEnum.GRANT_ROLES_TO_USER_ERR, sysGrantUserToRole.getUserId());
    }

    /**
     * 取消用户角色授权
     *
     * @param userId - 用户编号
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/20 14:22
     */
    public Result terminateAllRoleToUser(final Long userId) {
//        1.验证用户存在
        SysUser sysUser = sysUserService.getById(userId);
        if (ConvertUtils.isEmpty(sysUser)) {
            return Result.errorsFormat(SysTipEnum.TERMINATE_ALL_ROLE_TO_USER_ERR_NON_USER, userId);
        }
//        2.撤销授权
        boolean terminate = sysUserService.terminateAllRoleToUser(userId);
        if (terminate) {
            return Result.ok();
        }
        return Result.errorsFormat(SysTipEnum.TERMINATE_ALL_ROLE_TO_USER_ERR, sysUser.getUsername());
    }

    /**
     * 修改密码
     *
     * @param sysUserChangePassword - 密码修改对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:25
     */
    @VerificationCaptcha(captcha = "#sysUserChangePassword.captcha", verificationCodeIdentification = "#sysUserChangePassword.verificationCodeIdentification")
    public Result changeUserPassword(SysUserChangePasswordRO sysUserChangePassword) {
//        1.验证用户存在
        Long userId = sysUserChangePassword.getUserId();
        SysUser sysUser = sysUserService.getById(userId);
        if (ConvertUtils.isEmpty(sysUser)) {
            return Result.errorsFormat(SysTipEnum.CHANGE_USER_PASSWORD_ERR_NON_USER, userId);
        }
//        2.修改密码
        /**
         * 这里不考虑清缓存：业务场景：管理员重置密码，用户不在线
         */
        boolean changeUserPassword = sysUserService.changeUserPassword(sysUser.getUsername(), sysUserChangePassword.getNewPassword());
        if (changeUserPassword) {
            return Result.ok();
        }
        return Result.errorsFormat(SysTipEnum.TERMINATE_ALL_ROLE_TO_USER_ERR, sysUser.getUsername());
    }

    /**
     * 查询组织机构下的用户接口
     *
     * @param pagingQueryUserByOrganizationIdDTO - 根据组织机构查询用户对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public Result pagingQueryUserByOrganizationIdentification(final PagingQueryUserByOrganizationIdDTO pagingQueryUserByOrganizationIdDTO) {
        SysOrganization sysOrganization = serviceBySysOrganizationService.getById(pagingQueryUserByOrganizationIdDTO.getOrganizationId());
        if (ConvertUtils.isEmpty(sysOrganization)) {
//            1.根据组织机构信息查询，该组织机构不存在
            return Result.errorsFormat(SysTipEnum.ORGANIZATION_QUERY_ERR);
        }
        Page<SysUserVO> sysUserList = sysUserOrganizationService.pagingQueryUserByOrganizationIdentification(pagingQueryUserByOrganizationIdDTO);
        return Result.ok(sysUserList);
    }

    /**
     * 查询组织机构下没有的用户接口
     *
     * @param pagingQueryUserByOrganizationIdDTO - 根据组织机构查询用户对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public Result pagingQueryUnauthorizedUser(final PagingQueryUserByOrganizationIdDTO pagingQueryUserByOrganizationIdDTO) {
        SysOrganization sysOrganization = serviceBySysOrganizationService.getById(pagingQueryUserByOrganizationIdDTO.getOrganizationId());
        if (ConvertUtils.isEmpty(sysOrganization)) {
//            1.根据组织机构信息查询，该组织机构不存在
            return Result.errorsFormat(SysTipEnum.ORGANIZATION_QUERY_ERR);
        }
        Page<SysUserVO> sysUserList = sysUserOrganizationService.pagingQueryUnauthorizedUser(pagingQueryUserByOrganizationIdDTO);
        return Result.ok(sysUserList);
    }

}
